home *** CD-ROM | disk | FTP | other *** search
Text File | 1998-04-30 | 10.2 KB | 438 lines | [TEXT/MPS ] |
- /*
- File: OTMulticastPitchSample.cp
-
- Contains: IP Multicast under UDP sample.
-
- Copyright: © 1993-1996 by Apple Computer, Inc., all rights reserved.
-
- */
-
- #ifndef __OPENTPTGLOBALNEW__
- #include <OpenTptGlobalNew.h>
- #endif
-
- #include <OpenTptInternet.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <Quickdraw.h>
-
- /*******************************************************************************
- ** Misc defines
- ********************************************************************************/
-
- const UInt8 kDefaultTTL = 3; // Normal IP multicast default is 1.
-
- /*******************************************************************************
- ** Globals
- ********************************************************************************/
-
- char gMulticastAddrStr[] = "235.1.2.3";
- InetPort gMulticastPort = 2345;
- InetHost gMulticastHost;
- InetAddress gMulticastAddr;
- EndpointRef gEndpt;
- char gMessage[256];
-
- /*******************************************************************************
- ** SetupMulticast
- ********************************************************************************/
-
- OSStatus SetupMulticast()
- {
- TEndpointInfo info;
- OSStatus err = kOTNoError;
- TBind req;
- InetAddress myAddr;
-
- fprintf(stderr, "The program will send packets on port <%d>\n", gMulticastPort);
-
- do
- {
- //
- // Get a UDP endpoint which can be used for IP Multicast sends and receives
- //
-
- gEndpt = OTOpenEndpoint(OTCreateConfiguration(kUDPName), 0, &info, &err);
- if ( gEndpt == NULL || err != kOTNoError )
- {
- fprintf(stderr, "ERROR: OpenEndpoint(UDP) failed with error <%d>\n", err);
- break;
- }
-
- //
- // Set up an Inet Address for the multicast group
- // using our multicast address string and defined port number.
- //
-
- OTInetStringToHost(gMulticastAddrStr, &gMulticastHost);
- OTInitInetAddress(&gMulticastAddr, gMulticastPort, gMulticastHost);
-
- //
- // Do a normal bind to any IP address on our system,
- // but use the multicast port so we can receive loopbacks at times.
- // OK to use req for both input and output.
- //
-
- OTInitInetAddress(&myAddr, gMulticastPort, 0);
- req.addr.len = sizeof(myAddr);
- req.addr.maxlen = sizeof(myAddr);
- req.addr.buf = (unsigned char *) &myAddr;
- err = gEndpt->Bind(&req, &req);
- if ( err != kOTNoError )
- {
- fprintf(stderr, "ERROR: Bind() failed with error <%d>\n", err);
- break;
- }
-
- //
- // Let IP know to listen for this multicast IP address on all interfaces.
- //
-
- TOptMgmt optReq;
- UInt8 optBuffer[ kOTOptionHeaderSize + sizeof(TIPAddMulticast) ];
- TOption* opt = (TOption*)optBuffer;
- TIPAddMulticast* addopt = (TIPAddMulticast*)opt->value;
-
- optReq.flags = T_NEGOTIATE;
- optReq.opt.len = sizeof(optBuffer);
- optReq.opt.buf = (UInt8*) optBuffer;
-
- opt->level = INET_IP;
- opt->name = IP_ADD_MEMBERSHIP;
- opt->len = sizeof(optBuffer);
-
- addopt->multicastGroupAddress = gMulticastHost;
- addopt->interfaceAddress = kOTAnyInetAddress;
-
- err = gEndpt->OptionManagement(&optReq, &optReq);
- if ( err != kOTNoError )
- {
- fprintf(stderr, "ERROR: OTOptionManagement() (add membership) failed with %d\n", err);
- break;
- }
-
- //
- // Setup time-to-live for multicast sends (defaults to 1)
- // Can reuse the TOptMgmt, but not Option itself is different.
- // While we could reuse the buffer above, I'll do it right to
- // demonstrate correctness.
- //
-
- UInt8 ttlOptBuffer[ kOTOneByteOptionSize ];
- TOption* ttlOpt = (TOption*)ttlOptBuffer;
-
- optReq.flags = T_NEGOTIATE;
- optReq.opt.len = sizeof(ttlOptBuffer);
- optReq.opt.buf = (UInt8*) ttlOptBuffer;
-
- ttlOpt->level = INET_IP;
- ttlOpt->name = IP_MULTICAST_TTL;
- ttlOpt->len = sizeof(ttlOptBuffer);
- *(char*)(ttlOpt->value) = kDefaultTTL;
-
- err = gEndpt->OptionManagement(&optReq, &optReq);
- if ( err != kOTNoError )
- {
- fprintf(stderr, "ERROR: OTOptionManagement() (set ttl) failed with %d\n", err);
- break;
- }
-
- //
- // Put the endpoint into nonblocking mode so we don't hang
- // when receiving messages in synchronous mode.
- //
-
- err = gEndpt->SetNonBlocking();
- if ( err != kOTNoError )
- {
- fprintf(stderr, "ERROR: SetNonBlocking() failed with %d\n", err);
- break;
- }
- } while (false);
- return ( err != kOTNoError );
- }
-
- Boolean gLoopbackState = true;
-
- void LoopbackToggle()
- {
- OSStatus err;
-
- gLoopbackState = !gLoopbackState;
- if ( gLoopbackState )
- fprintf(stderr, "Loopback on\n");
- else
- fprintf(stderr, "Loopback off\n");
-
- //
- // Turn off loopback - unless you want to receive your own packets back.
- //
-
- TOptMgmt optReq;
- UInt8 optBuffer[ kOTOneByteOptionSize ];
- TOption* opt = (TOption*)optBuffer;
-
- optReq.flags = T_NEGOTIATE;
- optReq.opt.len = sizeof(optBuffer);
- optReq.opt.buf = (UInt8*) optBuffer;
-
- opt->level = INET_IP;
- opt->name = IP_MULTICAST_LOOP;
- opt->len = sizeof(optBuffer);
- *(char *)(opt->value) = gLoopbackState;
-
- err = gEndpt->OptionManagement(&optReq, &optReq);
- if ( err != kOTNoError )
- {
- fprintf(stderr, "ERROR: OTOptionManagement() (loopback toggle) failed with %d\n", err);
- }
- }
-
-
- void Cleanup()
- {
- gEndpt->Close();
- }
-
- void RecvLoop()
- {
- /*
- * This loop receives all messages waiting on the stream.
- * It operates in synchronous but nonblocking mode.
- * If there are no messages waiting, we go get another one to send.
- * Loopback messages (when the toggle is one) will be received too.
- */
-
- OSStatus err;
- TUnitData unitdata;
- InetAddress addr;
- OTFlags flags;
- char remoteAddr[32];
-
- while (true)
- {
- OTMemzero(remoteAddr, sizeof(remoteAddr));
- OTMemzero(gMessage, sizeof(gMessage));
- unitdata.addr.maxlen = sizeof(addr);
- unitdata.addr.buf = (unsigned char*) &addr;
- unitdata.opt.maxlen = 0;
- unitdata.opt.buf = 0;
- unitdata.udata.maxlen = sizeof(gMessage);
- unitdata.udata.buf = (UInt8*) gMessage;
- err = gEndpt->RcvUData( &unitdata, &flags);
- if ( err != kOTNoError )
- {
- if ( err == kOTNoDataErr )
- {
- return;
- }
- else
- {
- fprintf(stderr, "ERROR: RcvUData() failed with %d\n", err);
- break;
- }
- }
- OTInetHostToString( addr.fHost, remoteAddr);
- fprintf(stderr, "IP multicast from <%s>:%s\n", remoteAddr, gMessage);
- fflush(stderr);
- }
- }
-
- void SendLoop()
- {
- TUnitData unitdata;
- short len;
- Boolean done = false;
-
- /*
- * This routine is a loop which will get one message for the user,
- * send if via IP multicast, and then check for any received messages
- * and print them out.
- */
- while ( !done )
- {
- OTMemzero(gMessage, sizeof(gMessage));
- fprintf(stderr, "Message to send (hit return to quit)?\n");
- gets((char *) gMessage);
- len = OTStrLength((char *) gMessage);
- if ( len != 0 )
- {
- unitdata.udata.len = len;
- unitdata.udata.buf = (UInt8*) gMessage;
- unitdata.opt.len = 0;
- unitdata.opt.buf = NULL;
- unitdata.addr.len = sizeof(gMulticastAddr);
- unitdata.addr.buf = (unsigned char *)&gMulticastAddr;
- gEndpt->SndUData( &unitdata);
- RecvLoop();
- LoopbackToggle();
- fflush(stderr);
- }
- else
- done = true;
- }
- }
-
-
- void ShowEndpointOptions()
- {
- /*
- * This function retrieves and displays
- * the IP and UDP endpoint options for this endpoint.
- */
-
- OSStatus err;
- TOptMgmt* ret = (TOptMgmt*)OTAlloc(gEndpt, T_OPTMGMT, T_OPT, &err);
-
-
- do
- {
- fprintf(stderr, "Current Readable IP Option Settings for endpoint @ %08lX:\n", gEndpt);
- if ( ret == NULL )
- {
- fprintf(stderr, "ERROR: could not allocate TOptMgmt structure (%d)\n", err);
- break;
- }
- //
- // Get the current IP options
- //
- TOptMgmt req;
- TOptionHeader option;
-
- option.len = kOTOptionHeaderSize;
- option.level = INET_IP;
- option.name = T_ALLOPT;
-
- req.opt.buf = (UInt8*)&option;
- req.opt.len = kOTOptionHeaderSize;
- req.flags = T_CURRENT;
-
- err = gEndpt->OptionManagement(&req, ret);
- if ( err != kOTNoError )
- {
- fprintf(stderr, "ERROR: OptionManagement T_CURRENT request returned %d\n", err);
- break;
- }
- //
- // Now, let's print the options
- //
- {
- TOption* opt = (TOption*)ret->opt.buf;
- char string[512];
-
- err = OTCreateOptionString("ip", &opt, ret->opt.buf + ret->opt.len,
- string, sizeof(string));
-
- if ( err == kOTNoError )
- {
- char* str = string;
- size_t len = 0;
- while ( true )
- {
- char* temp = strchr(str, ',');
- if ( temp == NULL )
- {
- fprintf(stderr, "%s\n", str);
- break;
- }
- if ( len + temp - str + 1 > 80 )
- {
- fprintf(stderr, "\n");
- if ( *str == ' ' )
- str += 1;
- len = 0;
- }
- fprintf(stderr, "%*.*s", temp - str + 1, temp - str + 1, str);
- len += temp - str + 1;
- str = temp + 1;
- }
- }
- }
-
- TOption* opt = OTFindOption(ret->opt.buf, ret->opt.len, INET_IP, IP_MULTICAST_TTL);
-
- if ( opt == NULL )
- fprintf(stderr, "ERROR:OptionManagement did not have IP_MULTICAST_TTL in returned options\n");
-
- //
- // Get the current UDP options
- //
- fprintf(stderr, "Current Readable UDP Option Settings for endpoint @ %08lX:\n", gEndpt);
- option.len = kOTOptionHeaderSize;
- option.level = INET_UDP;
- option.name = T_ALLOPT;
-
- req.opt.buf = (UInt8*)&option;
- req.opt.len = kOTOptionHeaderSize;
- req.flags = T_CURRENT;
-
- err = gEndpt->OptionManagement(&req, ret);
- if ( err != kOTNoError )
- {
- fprintf(stderr, "ERROR: OptionManagement T_CURRENT request returned %d\n", err);
- break;
- }
- //
- // Now, let's print the options
- //
- {
- TOption* opt = (TOption*)ret->opt.buf;
- char string[512];
-
- err = OTCreateOptionString("udp", &opt, ret->opt.buf + ret->opt.len,
- string, sizeof(string));
-
- if ( err == kOTNoError )
- {
- char* str = string;
- size_t len = 0;
- while ( true )
- {
- char* temp = strchr(str, ',');
- if ( temp == NULL )
- {
- fprintf(stderr, "%s\n", str);
- break;
- }
- if ( len + temp - str + 1 > 80 )
- {
- fprintf(stderr, "\n");
- if ( *str == ' ' )
- str += 1;
- len = 0;
- }
- fprintf(stderr, "%*.*s", temp - str + 1, temp - str + 1, str);
- len += temp - str + 1;
- str = temp + 1;
- }
- }
- }
-
- } while ( false );
- OTFree(ret, T_OPTMGMT);
- }
-
-
- void Inits()
- {
- InitGraf(&qd.thePort);
- if ( InitOpenTransport() != kOTNoError )
- {
- fprintf(stderr, "MulticastPitchSample: Could not initialize ASLM\n");
- exit(1);
- }
- }
-
- void main()
- {
- Inits();
- if ( SetupMulticast() == kOTNoError )
- {
- ShowEndpointOptions();
- SendLoop();
- Cleanup();
- }
- }
-
-